package boardgamer.yavalath.client.lobby;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import boardgamer.common.CheckedCyclicIterator;
import boardgamer.common.client.Button;
import boardgamer.common.client.ClickableButton;
import boardgamer.common.client.Display;
import boardgamer.common.client.Drawable;
import boardgamer.common.client.HasEventHandler;
import boardgamer.common.client.layout.BitmapLayout;
import boardgamer.common.client.layout.HasLayout;
import boardgamer.common.client.layout.MutableBitmapLayout;
import boardgamer.yavalath.client.resources.ImageHandler;
import boardgamer.yavalath.client.resources.SoundHandler;
import boardgamer.yavalath.common.YavalathPlayerState;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;

/**
 * @author garysoed
 */
public class PlayerModePicker implements Drawable, HasLayout, HasEventHandler {

  private final PlayerNamePicker namePicker;
  private final CheckedCyclicIterator<YavalathPlayerState.PlayerMode> playerModeIterator;
  private final ClickableButton button;
  private final InnerButton innerButton;
  private YavalathPlayerState.PlayerMode playerMode;

  public PlayerModePicker(int color, YavalathPlayerState.PlayerMode playerMode,
    Predicate<YavalathPlayerState.PlayerMode> playerModePredicate, PlayerNamePicker namePicker) {
    this.namePicker = namePicker;
    this.playerModeIterator = new CheckedCyclicIterator<YavalathPlayerState.PlayerMode>(
        ImmutableList.copyOf(YavalathPlayerState.PlayerMode.values()),
        playerModePredicate);

    this.playerMode = playerMode;
    this.innerButton = new InnerButton(playerMode, color);
    InnerButtonGlow innerButtonGlow = new InnerButtonGlow(color);
    this.button = new ClickableButton(innerButton, innerButtonGlow);
    namePicker.setPlayerMode(playerMode);
  }

  public YavalathPlayerState.PlayerMode getPlayerMode() {
    return playerMode;
  }

  @Override
  public void draw(Canvas canvas) {
    button.draw(canvas);
  }

  @Override
  public void handleEvent(float eventX, float eventY, int eventAction) {
    button.handleEvent(eventX, eventY, eventAction);
  }

  @Override
  public RectF getCollisionBox() {
    return button.getCollisionBox();
  }

  @Override
  public void setBoundingRect(RectF boundingRect) {
    button.setBoundingRect(boundingRect);
  }

  @Override
  public RectF getBoundingRect() {
    return button.getBoundingRect();
  }

  private void changeMode() {
    YavalathPlayerState.PlayerMode nextMode = playerModeIterator.next();
    innerButton.setPlayerMode(nextMode);
    namePicker.setPlayerMode(nextMode);
    playerMode = nextMode;
  }

  private Bitmap getPlayerModeBitmap(YavalathPlayerState.PlayerMode playerMode) {
    switch (playerMode) {
      case CLOSED:
        return ImageHandler.closedButton;
      case HUMAN:
        return ImageHandler.humanButton;
      case AI:
        return ImageHandler.aiButton;
      default:
        throw new UnsupportedOperationException(playerMode + " has no bitmap");
    }
  }

  private class InnerButton implements Button {

    private final Paint backgroundPaint;
    private MutableBitmapLayout background;

    public InnerButton(YavalathPlayerState.PlayerMode playerMode, int color) {
      this.backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      this.backgroundPaint.setColorFilter(new LightingColorFilter(color, 0));

      this.background = new MutableBitmapLayout(
          getPlayerModeBitmap(playerMode), this.backgroundPaint);
    }

    public void setPlayerMode(YavalathPlayerState.PlayerMode playerMode) {
      background.setBitmap(getPlayerModeBitmap(playerMode));
    }

    @Override
    public void draw(Canvas canvas) {
      background.draw(canvas);
    }

    @Override
    public void handleEvent(float eventX, float eventY, int eventAction) {
      if (eventAction == MotionEvent.ACTION_UP && getCollisionBox().contains(eventX, eventY)) {
        SoundHandler.playWave(SoundHandler.buttonSound);
        PlayerModePicker.this.changeMode();
      }
    }

    @Override
    public RectF getCollisionBox() {
      return getBoundingRect();
    }

    @Override
    public void setBoundingRect(RectF boundingRect) {
      background.setBoundingRect(boundingRect);
    }

    @Override
    public RectF getBoundingRect() {
      return background.getBoundingRect();
    }
  }

  private class InnerButtonGlow implements Display {

    private final Paint glowPaint;
    private BitmapLayout glow;

    public InnerButtonGlow(int color) {
      this.glowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      this.glowPaint.setColorFilter(new LightingColorFilter(color, 0));
      this.glow = new BitmapLayout(ImageHandler.playerModeGlow, glowPaint);
    }

    @Override
    public void draw(Canvas canvas) {
      glow.draw(canvas);
    }

    @Override
    public void setBoundingRect(RectF boundingRect) {
      glow.setBoundingRect(boundingRect);
    }

    @Override
    public RectF getBoundingRect() {
      return glow.getBoundingRect();
    }
  }
}
